﻿using RockBus.Configuration;
using RockBus.PipelineComponent.Interfaces;
using System;
using System.IO;
using System.ServiceModel.Channels;
using System.Xml;
using System.Xml.Xsl;

namespace RockBus.PipelineComponent.Xml
{
    public class TransformationPipelineComponent : IPipelineComponent
    {
        public TransformationPipelineComponent(IPipelineComponentConfiguration configuration)
        {
            this.Configuration = configuration;
            this.XsltFileName = this.Configuration["XsltFileName"];
            this.SoapAction = this.Configuration["SoapAction"];

            this._compiledTransform = new Lazy<XslCompiledTransform>(CreateCompiledTransform, true);
        }

        public IPipelineComponentConfiguration Configuration { get; private set; }

        private string XsltFileName { get; set; }

        private string SoapAction { get; set; }

        private readonly Lazy<XslCompiledTransform> _compiledTransform;

        private XslCompiledTransform CompiledTransform { get { return this._compiledTransform.Value; } }

        private XslCompiledTransform CreateCompiledTransform()
        {
            string stylesheetUri = Path.Combine(ServiceBusConfigurationSection.Instance.Extensions.ContentFolder, this.XsltFileName);
            var compiledTransform = new XslCompiledTransform();
            compiledTransform.Load(stylesheetUri);
            return compiledTransform;
        }

        public Message Execute(Message message, IPipelineContext pipelineContext)
        {
            var ms = new MemoryStream();
            using (var xdr = message.GetReaderAtBodyContents())
            {
                this.CompiledTransform.Transform(xdr, null, ms);
                ms.Position = 0;

#if DEBUG
                var sreader = new StreamReader(ms);
                var test = sreader.ReadToEnd();
                ms.Position = 0;
#endif

                var xr = XmlReader.Create(ms);
                xr.MoveToContent();
                var newMessage = pipelineContext.MessageFactory.CreateMessage(xr, this.SoapAction ?? message.Headers.Action, message);
                return newMessage;
            }
        }
    }
}